﻿(function($) {
    Sw.Namespace("$.sw");
    $.fn.extend({
        combox: function(options) {
            return new $.sw.combox(this, options);
        }
    });
    $.sw.combox = Class({
        input: null,
        hidField: false,
        picker: null,
        wrapper: null,
        options: null,
        store: null,
        container: null,
        shadow: null,
        selectedItem: false,
        textAlias: null,
        valueAlias: false,
        query: null,
        initialize: function(input, options) {
            this.input = $(input);
            this.options = $.extend({}, $.sw.combox.defaults, options);
            this.store = this.options.store;
            this.initComponent(input);
        },
        initComponent: function() {
            this.input.css("width", this.options.width).val(this.options.emptyText).focus(function() { $(this).val(""); });
            this.wrapper = $(this.input).wrap("<div/>").parent().addClass(this.options.comboxCss);
            if (this.options.hidField) {
                this.hidField = $("<input/>").attr({ "id": "h" + this.input.attr("id"), "type": "hidden" }).appendTo(this.wrapper);
            }
            this.picker = $("<div />").hoverClass("picker-hover").appendTo(this.wrapper).addClass(this.options.pickerCss).css("left", this.input.width());
            this.render();
            this.addEvents();
        },
        render: function() {
            if (this.store) {
                var me = this;
                this.textAlias = me.store.fields.text;
                var maxWidth = [];
                this.valueAlias = me.store.fields.value == undefined ? "" : me.store.fields.value;
                this.container = $("<div/>").click(function(e) { Sw.stop(e); })
                                        .width(Sw.Size.fromElement(this.input, 2).width + 7).appendTo($(document.body));
                this.options.autoHeight ? this.container.css("max-height", this.options.height) : this.container.css("height", this.options.height);
                var listItems = $("<ul/>").appendTo(this.container);
                $(this.store.data).each(function(index, item) {
                    maxWidth.push($("<li/>").hoverClass("hover").appendTo(listItems).html("<span>" + item[me.textAlias] + "</span>").attr({ "stext": item[me.textAlias], "svalue": me.valueAlias == "" ? "" : item[me.valueAlias] }).click(function(e) {
                        me.selectedChange(item); Sw.stop(e);
                    }).find("span").outerWidth());
                });
                maxWidth = maxWidth.sort(function(a, b) {
                    return a - b;
                });
                if (maxWidth[maxWidth.length - 1] >= this.container.width()) {
                    $("li", this.container).width(maxWidth[maxWidth.length - 1] + 3);
                }
                this.container.addClass(this.options.containerCss);
                if (this.options.selectedItem) {
                    this.selectedItem = this.getDefaultSeletecd(this.options.selectedItem);
                    this.renderSeletecd();
                }
                var size = Sw.Size.fromElement(this.input, 2);
                var offset = Sw.Offset.fromElement(this.input).add(0, size.height).applyTo(this.container);
                this.shadow = new $.sw.shadow(this.container);
                //或者这样写也行this.shadow = $(this.container).shadow();
                maxWidth = listItems = size = offset = null;
            }

        },
        removeClass: function() {
            $("li", this.container).removeClass("selected");
        },
        getDefaultSeletecd: function(defaultValue) {
            if (this.valueAlias != "") {

                return $(this.store.data).jget(defaultValue[this.valueAlias], this.valueAlias);
            }
            else {
                return defaultValue;
            }
        },
        renderSeletecd: function() {
            if (this.selectedItem) {
                this.setValue(this.selectedItem);
                this.removeClass();
                if (this.valueAlias != "") {

                    $("li[svalue='" + this.getValue() + "']", this.container).first().addClass("selected");
                }
                else {
                    $("li[stext='" + this.getText() + "']", this.container).first().addClass("selected");
                }
            }

        },
        hide: function() {
            this.container.hide();
            this.shadow.hide();
            this.input.removeClass("focus");
            this.picker.removeClass("picker-focus");

        },
        show: function() {
            this.container.show();
            $("ul li", this.container).show();
            this.input.addClass("focus");
            this.picker.addClass("picker-focus");
            this.shadow.refresh();
            this.shadow.show();
        },
        addEvents: function() {
            var me = this;
            this.wrapper.click(function() {
                me.input.focus();
                me.show();
                $(document).one("click", function(event) {
                    me.hide();
                });
                return false;
            });
            //key
            this.input.keyup(function(e) {

                me.onKeyup(e);
            });

        },
        getSeletedItem: function() {
            var currenSelected = this.container.children('ul').children('li.selected');
            return currenSelected.length > 0 ? currenSelected.first() : false;
        },
        prevResult: function() {

            $currenSelected = this.getSeletedItem();
            if ($currenSelected)
                $currenSelected.removeClass("selected").prev("li:visible").addClass("selected");
            else
                $("ul li:visible", this.container).last().addClass("selected");

        },
        nextResult: function() {

            $currenSelected = this.getSeletedItem();
            if ($currenSelected)
                $currenSelected.removeClass("selected").next("li:visible").addClass("selected");
            else
                $("ul li:visible", this.container).first().addClass("selected");

        },
        onKeyup: function(e) {

            if ((/27$|38$|40$/.test(e.keyCode)) || (/^13$|^9$/.test(e.keyCode) && this.getSeletedItem())) {
                Sw.stop(e);
                switch (e.keyCode) {
                    case Sw.keyCode.Up:
                        this.prevResult();
                        break;
                    case Sw.keyCode.Down:
                        this.nextResult();
                        break;
                    case 13:
                        this.selectedResult();
                        break;
                    case Sw.keyCode.Esc:
                        this.hide();
                        break;
                }
            }
            else if (this.input.val() != this.query) {
                this.query = this.input.val();
                this.filter();
            }
        },
        filter: function() {  //是否异步调用
            if (this.options.async) {  //do something()
            }
            else {
                var reg = new RegExp('^' + this.query + '.*$', 'im');
                $("ul li", this.container).each(function() {
                    if (reg.test($(this).attr("stext")))
                        $(this).show();
                    else
                        $(this).hide();

                });
                this.shadow.refresh();
            }

        },
        setValue: function(item) {
            this.input.val(item[this.textAlias]);
            if (this.hidField && this.valueAlias && item[this.valueAlias]) {
                this.hidField.val(item[this.valueAlias]);
            }
        },
        selectedResult: function() {
            var text = this.textAlias;
            var selectedResult = this.getSeletedItem();
            var selectedItem = '{"' + this.textAlias + '":"' + selectedResult.attr("stext") + '","' + this.valueAlias + '":"' + selectedResult.attr("svalue") + '"}';
            this.selectedChange($.parseJSON(selectedItem));
        },
        selectedChange: function(item) {
            this.selectedItem = item;
            this.renderSeletecd();
            var evt = this.options.selectedChange;
            if (evt && $.isFunction(evt)) {
                evt.call(this, this.getText(), this.getValue());
            }
            evt = null;
            this.hide();
        },
        getText: function() { return this.input.val(); },
        getValue: function() { return this.hidField ? this.hidField.val() : ""; }
    })
    $.extend($.sw.combox, {
        defaults: {
            hidField: true,
            comboxCss: "sw-combox",
            pickerCss: "picker",
            containerCss: "sw-combox-container",
            emptyText: "select a value",
            width: 100,
            height: 200,
            autoHeight: true,
            filter: true,
            async: false,
            selectedChange: false,
            store: false,
            selectedItem: false

        }
    });
})(jQuery);